package com.runa.rccprotocol.analysis.En13757.decoder;

import com.runa.protocol.util.ByteUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * @author diandian
 * @Date 2021/11/10 13:23
 */
public class VIF {
    private byte vifByte;

    private int base = 10;

    private int exponent;

    private VIF_Type dataType;

    private AbsEnDecoder decoder;

    private List<VIFE> vifeList;

    public double handle(Integer data) {
        double pow = Math.pow(base, exponent);
        return data * pow;
    }

    public VIF(AbsEnDecoder decoder) {
        this.decoder = decoder;
        init();
    }

    public byte getVifByte() {
        return vifByte;
    }

    public VIF_Type getDataType() {
        return dataType;
    }

    public void setDataType(VIF_Type dataType) {
        this.dataType = dataType;
    }

    public enum VIF_Type {
        accHeat, //单位wh
        accHeat2, //单位 j
        accFlow, //单位 m³
        power,//功率 w
        power2,//功率 J/h
        flow,  //m3/h
        flow1, //m3/min
        flow2, //m3/s
        date_f,
        workTime, inTem, outTem, heat
    }

    private void init() {
        vifByte = decoder.next();
        //如果vif在下一个字节
        this.vifNext();
        for (int start = 3; start >= 0; start--) {
            int byBits = ByteUtil.getByBits(vifByte, start, 7-start);
            this.setDataType(byBits, start);
            if (this.dataType != null) {
                break;
            }
        }
        this.setVIFE(vifByte);
    }

    //vif是否在下一个字节
    private boolean vifNext() {
        boolean re = (0xFB == (vifByte & 0xff) || 0xFD == (vifByte & 0xff));
        if (re) {
            vifByte = decoder.next();
        }
        return re;
    }

    //解析vif 获取量纲，返回
    private void setDataType(int byBits, int start) {
        int unitBits = ByteUtil.getByBits(vifByte, 0, start);
        switch (byBits) {
            case 0x00:
                //0000  能量  wh
                this.dataType = VIF_Type.accHeat;
                this.exponent = unitBits - 3;
                break;
            case 0x01:
                //0001 能量  J
                this.dataType = VIF_Type.accHeat2;
                this.exponent = unitBits;
                break;
            case 0x02:
                //0010 体积 m³
                this.dataType = VIF_Type.accFlow;
                this.exponent = unitBits - 6;
                break;
            case 0x03:
                //0011 质量
                this.exponent = unitBits - 3;
                break;
            case 0x05:
                //0101 功率
                this.dataType = VIF_Type.power;
                this.exponent = unitBits - 3;
                break;
            case 0x06:
                //0110 功率
                this.dataType = VIF_Type.power2;
                this.exponent = unitBits;
                break;
            case 0x07:
                //0111 体积流量
                this.dataType = VIF_Type.flow;
                this.exponent = unitBits - 6;
                break;
            case 0x08:
                //1000 外部体积流量
                this.dataType = VIF_Type.flow1;
                this.exponent = unitBits - 7;
                break;
            case 0x09:
                //1001 外部体积流量
                this.dataType = VIF_Type.flow2;
                this.exponent = unitBits - 9;
                break;
            case 0x0A:
                //1010 质量流量
                this.exponent = unitBits - 3;
                break;
            case 0x16:
                //10110 进水温度
                this.dataType = VIF_Type.inTem;
                this.exponent = unitBits - 3;
                break;
            case 0x17:
                //10111 回水温度
                this.dataType = VIF_Type.outTem;
                this.exponent = unitBits - 3;
                break;
            case 0x18:
                //11000 温差
                this.exponent = unitBits - 3;
                break;
            case 0x19:
                //11001 外部温度
                this.exponent = unitBits - 3;
                break;
            case 0x1A:
                //11010 压力
                this.exponent = unitBits - 3;
                break;
            case 0x6D:
                //110 1101 时间 F
                this.dataType = VIF_Type.date_f;
                break;
        }
    }

    public void setVIFE(byte data) {
        int e = ByteUtil.getByBit(data, 7) & 0xff;
        boolean have = 0x1 == e;
        if (!have) {
            return;
        }
        if (vifeList == null) {
            vifeList = new ArrayList<>();
        }
        byte vife = decoder.next();
        vifeList.add(new VIFE(vife));
        setVIFE(vife);
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("{");
        sb.append("\"vifByte\":")
                .append(String.format("%02X", vifByte));
        sb.append(",\"base\":")
                .append(base);
        sb.append(",\"exponent\":")
                .append(exponent);
        sb.append(",\"dataType\":")
                .append(dataType);
        sb.append(",\"vifeList\":")
                .append(vifeList == null ? null : vifeList.size());
        sb.append('}');
        return sb.toString();
    }

    public class VIFE {
        private byte vife;

        public VIFE(byte vife) {
            this.vife = vife;
        }
    }
}